#include "app_modbus.h"
#include <modbus/modbus.h>
#include <errno.h>
#include <unistd.h>
#include "log.h"


static modbus_t *modbus_handle;

/**
 * @brief modbus初始化
 */
int app_modbus_init(char * dev_file_name)
{
    //1  初始化句柄(上下文)
     modbus_handle = modbus_new_rtu(dev_file_name, 115200, 'N', 8, 1);
      if (modbus_handle == NULL) {
        log_error("Unable to create the libmodbus context:,reason:%s\n",modbus_strerror(errno));
        return -1;
    }
    //2 设置：  日志打印   收发方向控制   超时设置    
     modbus_set_debug(modbus_handle, TRUE);

     modbus_rtu_set_rts(modbus_handle, MODBUS_RTU_RTS_NONE) ;// 不用手动控制方向引脚 靠收发芯片自己判断

     modbus_set_response_timeout(modbus_handle, 1, 0); //1秒超时
    
    //3  连接
    if (modbus_connect(modbus_handle) == -1) {
        log_error("Unable to connect:,reason:%s\n",modbus_strerror(errno));
        return -1;
    }

    return 0;
}



/**
 * @brief 写线圈 
 * 1 flush 
 * 2 设置 slave_id
 * 3 读写操作
 * 
 */
int app_modbus_writeCoil(int slave_id, int coil_addr, int reg_num, uint8_t* coil_value)
{
    //1 flush 
    modbus_flush(modbus_handle);
    //2 设置 slave_id
    modbus_set_slave(modbus_handle, slave_id);
    //3 读写操作
   int ret=  modbus_write_bits(modbus_handle, coil_addr, reg_num, coil_value);
    if(ret < 0)
    {
        // 进行一次重试
        log_warn("modbus_write_bits error,reason:%s , retrying....\n",modbus_strerror(errno));
        usleep(5000); //等待5ms
        ret= modbus_write_bits(modbus_handle, coil_addr, reg_num, coil_value);
        if(ret < 0)
        {
            log_error("modbus_write_bits error,reason:%s\n",modbus_strerror(errno));
            return -1;
        }
    }
    return 0;
}


/**
 * @brief 读线圈
 */
int app_modbus_readCoil(int slave_id, int coil_addr, int reg_num, uint8_t* coil_buff)
{
        //1 flush 
    modbus_flush(modbus_handle);
    //2 设置 slave_id
    modbus_set_slave(modbus_handle, slave_id);
    //3 读写操作
   int ret=  modbus_read_bits(modbus_handle, coil_addr, reg_num, coil_buff);
    if(ret < 0)
    {
        // 进行一次重试
        log_warn("modbus_read_bits error,reason:%s , retrying....\n",modbus_strerror(errno));
        usleep(5000); //等待5ms
        ret= modbus_read_bits(modbus_handle, coil_addr, reg_num, coil_buff);
        if(ret < 0)
        {
            log_error("modbus_read_bits error,reason:%s\n",modbus_strerror(errno));
            return -1;
        }
    }
    return 0;

}


/**
 * @brief 写保持寄存器    目标角度 、 最大速度
 */
int app_modbus_writeHoldReg(int slave_id, int reg_addr, int reg_num, uint16_t* reg_value)
{
        //1 flush 
    modbus_flush(modbus_handle);
    //2 设置 slave_id
    modbus_set_slave(modbus_handle, slave_id);
    //3 读写操作
   int ret=  modbus_write_registers(modbus_handle, reg_addr, reg_num, reg_value);
    if(ret < 0)
    {
        // 进行一次重试
        log_warn("modbus_write_registers error,reason:%s , retrying....\n",modbus_strerror(errno));
        usleep(5000); //等待5ms
        ret= modbus_write_registers(modbus_handle, reg_addr, reg_num, reg_value);
        if(ret < 0)
        {
            log_error("modbus_write_registers error,reason:%s\n",modbus_strerror(errno));
            return -1;
        }
    }
    return 0;

}


/**
 * @brief 读输入寄存器    当前角度  电机状态
 * 
 */
int app_modbus_readInputReg(int slave_id, int reg_addr, int reg_num, uint16_t* reg_buff) 
{
        //1 flush 
    modbus_flush(modbus_handle);
    //2 设置 slave_id
    modbus_set_slave(modbus_handle, slave_id);
    //3 读写操作
   int ret=  modbus_read_input_registers(modbus_handle, reg_addr, reg_num, reg_buff) ;
    if(ret < 0)
    {
        // 进行一次重试
        log_warn("modbus_read_input_registers error,reason:%s , retrying....\n",modbus_strerror(errno));
        usleep(5000); //等待5ms
        ret= modbus_read_input_registers(modbus_handle, reg_addr, reg_num, reg_buff);
        if(ret < 0)
        {
            log_error("modbus_read_input_registers error,reason:%s\n",modbus_strerror(errno));
            return -1;
        }
    }
    return 0;

}

/**
 * @brief 销毁modbus 句柄
 */
void app_modbus_destroy(void)
{
    modbus_close(modbus_handle);
    modbus_free(modbus_handle);
}